package com.duan.nowcoder.community.service;

import com.duan.nowcoder.community.entity.User;
import com.duan.nowcoder.community.util.CommunityConstant;
import com.duan.nowcoder.community.util.RedisKeyUtil;
import com.duan.nowcoder.community.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class FollowServiceImpl implements FollowService, CommunityConstant {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private UserService userService;

    @Override
    public void follow(int entityType, int entityId, int userId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                //放粉丝
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
                //放博主
                String followeeKey = RedisKeyUtil.getFolloweeKey(entityType, userId);
                boolean isMember = redisUtil.zSHasKey(followeeKey, entityId);
                operations.multi();
                if (isMember) {
                    operations.opsForZSet().remove(followerKey, userId);
                    operations.opsForZSet().remove(followeeKey, entityId);
                } else {
                    operations.opsForZSet().add(followerKey, userId, System.currentTimeMillis());
                    operations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis());
                }
                return operations.exec();
            }
        });
    }


    //关注的博主数
    @Override
    public long followeeCount(int userId, int entityType) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(entityType, userId);
        return redisUtil.zSSize(followeeKey);
    }

    //粉丝数
    @Override
    public long followerCount(int userId, int entityType) {
        String followerKey = RedisKeyUtil.getFollowerKey(entityType, userId);
        return redisUtil.zSSize(followerKey);
    }

    //查询是否已关注该博主
    @Override
    public int isFollower(int userId, int entityType, int entityId) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(entityType, userId);
        return redisUtil.zSHasKey(followeeKey, entityId) ? 1 : 0;
    }

    //获得该用户的关注博主的列表
    @Override
    public List<Map<String, Object>> findFolloweeList(int userId, int offset, int limit, int meId) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(ENTITY_TYPE_USER, userId);
        //获得关注博主列表的集合
        Set<Integer> followees = redisUtil.zRevRange(followeeKey, offset, offset + limit - 1);
        if (followees == null) return null;
        List<Map<String, Object>> followeeList = new ArrayList<>();
        for (Integer id : followees) {
            User user = userService.findUserById(id);
            Map<String, Object> map = new HashMap<>();
            map.put("user", user);
            //查询关注时间
            Double score = redisUtil.zSScore(followeeKey, id);
            map.put("followTime", new Date(score.longValue()));
            //登录用户对于该用户的关注状态
            map.put("followState", isFollower(meId, ENTITY_TYPE_USER, id));
            followeeList.add(map);
        }
        return followeeList;
    }

    //获得粉丝列表
    @Override
    public List<Map<String, Object>> findFollowerList(int userId, int offset, int limit, int meId) {
        String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);
        Set<Integer> followers = redisUtil.zRevRange(followerKey, offset, offset + limit - 1);
        if (followers == null) return null;
        List<Map<String, Object>> followerList = new ArrayList<>();
        for (Integer id : followers) {
            Map<String, Object> map = new HashMap<>();
            User user = userService.findUserById(id);
            map.put("user", user);
            Double score = redisUtil.zSScore(followerKey, id);
            map.put("followTime", new Date(score.longValue()));
            map.put("followState", isFollower(meId, ENTITY_TYPE_USER, id));
            followerList.add(map);
        }
        return followerList;
    }
}
